#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory>
#include <variant>
#include "klib/ansi_color.hpp"
#include "klib/log.hpp"
#include "klib/utils.hpp"
#include "klib/net.hpp"
#include "klib/jsonwriter.hpp"
#include "klib/function_traits.hpp"

using namespace klib;

void run(std::initializer_list<std::pair<const char*, std::variant<int, std::string>>> list) {
    for (auto& v : list) {
        switch (v.second.index()) {
            case 0:
                std::printf("[int] %s = %d\n", v.first, std::get<0>(v.second));
                break;
            case 1:
                std::printf("[str] %s = %s\n", v.first, std::get<1>(v.second).c_str());
                break;
        }
    }
}

void test() {
    dstring_t<32> dstr;
    fmt::println("end char: [{}]", (uint8_t) *dstr.end());
    std::memset(dstr.data(), 'x', dstr.capacity());
    fmt::println("1: [{}]");
    std::printf("dstr = [%s], cap = %zu\n", dstr.data(), dstr.capacity());
}

template<typename FN>
void x22(FN&& fn) {
    using f = function_traits<FN>;
    fmt::println("fn param_count = {}", f::param_count);
    // fmt::println("func arg1 = {}", std::is_same_v<int, function_traits<FN>::param_type<0>>)
    fmt::println("func return type = {}", std::is_same_v<int, typename f::param_type<0>>);
    // fmt::println("func return type = {}", std::is_same_v<int, function_traits<decltype(fn)>::return_type>);
}

struct AA {
    int i;
    char c;
};

struct AT1 {
    AT1() { LOG_DEBUG("AT1 constructor"); }
    AT1(const AT1& src) { LOG_DEBUG("AT! copy"); }
    AT1(AT1&& src) { LOG_DEBUG("AT! move"); }
    ~AT1() { LOG_DEBUG("AT1 destroy"); }
};

struct AT2 {
    AT2(int n): xx(n) { LOG_DEBUG("AT2 constructor"); }

    AT1 at1;
protected:
    int xx;

    friend void ppp(AT2&);
};

void ppp(AT2& a) { LOG_DEBUG("at2.xx = {}", a.xx); }

int main() {
    KLIB_USE_UTF8;
    log::set_level(log::level_t::debug);
    test();

    run({{"kiven", 49}, {"hello", "world"}});

    int a = 33;
    // x22(run);
    // x22([](){});
    x22([a](int b, double c) -> int { return 0; });
    // x22([](int a, char c){ return 'a'; });

    AA *aaa = new AA{};
    AA *aa2 = new AA{3};
    std::printf("%d, %d\n", aaa->i, aa2->i);

    const char* axx = "kiven";
    char buf[128];
    char* pp = std::strcpy(buf, axx);
    std::printf("buf = [%s], buf: %p, pp: %p\n", buf, buf, pp);

    auto wn1 = std::snprintf(buf, 128, "%s", "12345678");
    auto wn2 = std::snprintf(buf, 8, "%s", "12345678");
    std::printf("wn1 = %d, wn2 = %d, [%s]\n", wn1, wn2, buf);

    AT2 at22(9);
    AT2 at23(std::move(at22));
    AT2 at24(at23);
    AT2 at25(25);
    ppp(at25);

    std::string mys("kiven"), mys1("kiven1");
    std::string_view mysv(mys1);
    std::printf("equal = %d\n", mys == mysv);
    return 0;
}